package com.test.spirngsecurity.conf;

import com.alibaba.fastjson.JSONObject;
import com.test.spirngsecurity.model.User;
import com.test.spirngsecurity.service.UserService;
import com.test.spirngsecurity.tool.ResultInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Configuration
public class DBWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
    UserService userService;
@Bean
    PasswordEncoder passwordEncoder(){
    return NoOpPasswordEncoder.getInstance();
}
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
    auth.userDetailsService(userService);
    }
    @Override
    protected void configure(HttpSecurity http)throws Exception{
    http.authorizeRequests()
            .antMatchers("/admin/**").hasRole("2")
            .antMatchers("/db/**").hasRole("1")
            .antMatchers("/user/**").hasRole("3")
            .antMatchers("/index.html").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login.html")
            .loginProcessingUrl("/login")
            .successHandler(new AuthenticationSuccessHandler() {
                @Override
                public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                    resp.setContentType("application/json;charset=utf-8");
                    PrintWriter out=resp.getWriter();
                    out.write(JSONObject.toJSONString(ResultInfo.success("登陆成功!",200)));
                    out.flush();
                    out.close();
                }
            })
            .failureHandler(new AuthenticationFailureHandler() {
                @Override
                public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {
                    resp.setContentType("application/json;charset=utf-8");
                    PrintWriter out=resp.getWriter();
                    if(e instanceof BadCredentialsException){
                        out.write(JSONObject.toJSONString(ResultInfo.failure("密码错误登陆失败!",401)));
                    }
                    else {
                        out.write(JSONObject.toJSONString(ResultInfo.failure("未知原因登陆失败!",401)));
                    }
                    out.flush();
                    out.close();
                }
            })

            .permitAll()
            .and()
            .logout()
            .logoutUrl("/logout")
//                .logoutSuccessUrl("/index.html") //由于配置了loLogoutSuccessHandler,就不生效
            .clearAuthentication(true)
            .invalidateHttpSession(true)
            .logoutSuccessHandler(new LogoutSuccessHandler() {
                @Override
                public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
                    resp.setContentType("application/json;charset=utf-8");
                    PrintWriter out=resp.getWriter();
                    out.write(JSONObject.toJSONString(ResultInfo.success("登出成功!",200)));
//                    resp.sendRedirect("/index.html");
                    out.flush();
                    out.close();

                }
            })
            .deleteCookies("JSESSIONID")
            .and()
            .csrf().disable();
    }
    @Bean
    RoleHierarchy roleHierarchy(){
        RoleHierarchyImpl roleHierarchy=new RoleHierarchyImpl();
        String hierarchy="ROLE_1 > ROLE_2 > ROLE_3";
        roleHierarchy.setHierarchy(hierarchy);
        return roleHierarchy;
    }
}
